from asyncore import read
from datetime import datetime
import json
from multiprocessing.spawn import prepare
import os
import sys
import pymongo

from data_reader.DataReader import DataReader
from data_reader.NsReader import NsReader
from data_reader.OrReader import OrReader
from utils.StatusThread import StatusThread
from utils.Timer import Timer

class Mongo:
    client = None
    table = ""
    data_dir = ""
    mongo_collection = None
    pcm_prefix = "Mongo_"
    mongo_pid = 18713

    def drop_table(self):
        # drop table and index if exists
        mongo_db = self.client['picsad']
        self.mongo_collection = mongo_db[self.table]
        self.mongo_collection.drop()

    def create_table(self):
        # create point cloud collection
        mongo_db = self.client['picsad']
        self.mongo_collection = mongo_db[self.table]

    def create_index(self):
        # create index on timestamp
        self.mongo_collection.create_index([('sweep', 1)])
        self.mongo_collection.create_index([('tstamp', 1)])

    def load_test(self, test_case):
        # load data from file
        reader_name = test_case["reader"]
        data_dir = test_case["dir"]
        self.data_dir = data_dir
        self.table = test_case["table"]
        self.index_name = self.table + "_tstamp_index"
            
        # load data reader
        loadermodule = "data_reader." + reader_name
        exec('from ' + loadermodule + ' import ' + reader_name)
        reader_class = getattr(sys.modules[loadermodule], reader_name)
        reader = reader_class(data_dir)

        timer = Timer()
        timer.Start()
        self.prepare()
        timer.StopAndRecord("Init")

        # start load data
        # first create a thread to record resources usage
        status = StatusThread(os.getpid(), self.pcm_prefix + "load", test_case["dir"])
        status.start()

        mongo_status = StatusThread(self.mongo_pid, "mongo_load", test_case["dir"])
        mongo_status.start()

        sweep = 0
        while reader.has_more_sweep():
            sweep += 1
            if sweep%10 == 1:
                print(sweep)
            points = reader.read_sweep()
            tstamp = reader.read_timestamp()
            timer.Start()
            self.load_data(sweep, points, tstamp)
            timer.Pause()

        timer.StopAndRecord("Load")
        status.end()
        mongo_status.end()

        status = StatusThread(os.getpid(), self.pcm_prefix + "close", test_case["dir"])
        status.start()
        mongo_status = StatusThread(self.mongo_pid, "mongo_close", test_case["dir"])
        mongo_status.start()
        timer.Start()
        self.close()
        timer.StopAndRecord("Close")
        timer.PrintAll()
        timer.Save(test_case["dir"] + self.pcm_prefix + "time.txt")
        status.end()
        mongo_status.end()


    def close(self):
        self.create_index()
        self.client.close()

    def prepare(self):
        self.client = pymongo.MongoClient('127.0.0.1', 27017)
        self.drop_table()
        self.create_table()


    def load_data(self, sweep, points, tstamp):
        # Execute copy
        data = []
        for p in points:
            data.append({
                'sweep': sweep,
                'x': p[0],
                'y': p[1],
                'z': p[2],
                'tstamp': tstamp
            })
        self.mongo_collection.insert_many(data, ordered=False, bypass_document_validation=True)

if __name__ == '__main__':
    # load config
    with open(os.getcwd() + '/config.json', 'r') as f:
        config = json.load(f)

    # start monitor the running process
    data_base_path = config["data_base_path"]
    for c in config["test_case"]:
        test_case = config["collect_dataset"][c]
        Mongo().load_test(test_case)
